#include "ui_ext.h"
#include "ui_events.h"

static const char *TAG = "UI_EXTEND";

// 手工添加gif函数
void ui_Screen1_gif_init(void) {
    ESP_LOGI(TAG, "ui_Screen1_gif_init");
    lv_obj_t *img_gif;
    img_gif = lv_gif_create(ui_Screen1);
    lv_gif_set_src(img_gif, &ui_img_1_gif);
    // 位置， 横向偏移，纵向便宜
    lv_obj_align(img_gif, LV_ALIGN_CENTER, 0, 40);
    ESP_LOGI(TAG, "ui_Screen1_gif_init finished.");
}

// 时间结构体
struct tm *timeinfo;
struct timeval tv = {
    .tv_sec = 0,
    .tv_usec = 0,
};

// 时间刷新回调函数
void ui_clock_update(lv_timer_t *timer) {
    gettimeofday(&tv, NULL);
    timeinfo = localtime(&tv.tv_sec);
    char time_str[9];
    sprintf(time_str, "%02d:%02d:%02d", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

    // 奇奇怪怪的编译校验。 不限制大小，会报错。
    int year = timeinfo->tm_year + 1900;
    int month = timeinfo->tm_mon + 1;
    int day = timeinfo->tm_mday;
    year = (year < 1970) ? 1970 : ((year > 9999) ? 9999 : year);
    month = (month < 1) ? 1 : ((month > 12) ? 12 : month);
    day = (day < 1) ? 1 : ((day > 31) ? 31 : day);

    char date_str[11];
    sprintf(date_str, "%04d/%02d/%02d", year,month, day);

    lv_label_set_text_fmt(ui_timeLabel, "%s", time_str);
    lv_label_set_text_fmt(ui_dateLabel, "%s", date_str);
}

// 时间定时器初始化
void ui_Screen1_timer_init(void) {
    lv_timer_t *timer_clock = lv_timer_create(ui_clock_update, 1000, NULL);
    ui_clock_update(timer_clock);
}

// 获取外部输入状态
// 当按钮被按下返回的是按钮的ID，而不是按钮的状态值, 所以目测同一时间只能按一个按钮
uint32_t my_btn_read(void) {
    return gpio_get_level(GPIO_NUM_0);
}

// 外部输入回调
void button_read_cb(lv_indev_t * indev, lv_indev_data_t * data) {
    int btn_id = my_btn_read();
    if (btn_id <= 0 ) {
        // 设置按钮状态与event
        /*Save the last button*/
        data->btn_id = btn_id; 
        data->key = LV_KEY_ENTER;
        data->state = LV_INDEV_STATE_PRESSED;
    } else {
        // 按钮被释放
        data->state = LV_INDEV_STATE_RELEASED;
    }
}

// 外部控制输入
// 可以是物理按键也可以是任何传感器
lv_obj_t *screens[4];
int current_screen_index = 0;
lv_group_t *screen_group;

void custom_indev_init(void) {
    //*Initialize the input device*/
    lv_indev_t * indev = lv_indev_create(); 
    lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD);
    lv_indev_set_read_cb(indev, button_read_cb);

    // 把按钮与屏幕捆绑到一组，让lvgl知道按钮的生效范围
    screen_group = lv_group_create();
    // 设置默认组，一定要在组件创建前，否则不生效
    // lv_group_set_default(screen_group);  
    lv_group_add_obj(screen_group, ui_Screen1);
    lv_indev_set_group(indev, screen_group);

    // 初始化屏幕数组
    screens[0] = ui_Screen1;
    screens[1] = ui_Screen2;
    screens[2] = ui_Screen3;
    screens[3] = ui_Screen4;
}

// 屏幕切换event
void screen_changed_event(lv_event_t * e){
    // 当屏幕切换时,从group中剔除本screen
    lv_group_remove_obj(screens[current_screen_index]);
    current_screen_index++;
    // 如果超过长度则重置
    if (current_screen_index >= sizeof(screens) / sizeof(screens[0])) {
        current_screen_index = 0;
    }
    // 当屏幕切换时,添加screen到group中
    lv_group_add_obj(screen_group, screens[current_screen_index]);
}


// 切换ota分区
static void ota_swich_to_app(int app_index) {
    // Initially assume the first OTA partition, which is typically 'ota_0'
    const esp_partition_t *next_partition = esp_ota_get_next_update_partition(NULL);

    // Iterate to find the correct OTA partition only if button ID is greater than 1
    if (app_index > 0 && app_index <= 5) {
        for (int i = 0; i < app_index; i++) {
            next_partition = esp_ota_get_next_update_partition(next_partition);
            if (!next_partition) break;  // If no next partition, break from the loop
        }
    }

    // For button 1, next_partition will not change, thus pointing to 'ota_0'
    if (next_partition && esp_ota_set_boot_partition(next_partition) == ESP_OK) {
        ESP_LOGI(TAG, "Setting boot partition to %s\n", next_partition->label);
        esp_restart();  // Restart to boot from the new partition
    } else {
        ESP_LOGI(TAG, "Failed to set boot partition");
    }
}

// 当页面被选择则启动ota切换
// *** 此方法需要在所有自定义ota程序中设置回调方式，否则切过去就回不来了 *** 

void change_ota_part(void) {
    // 获取当前页面数据
    lv_obj_t * scr = lv_scr_act();

}